#pragma once

#include <libtcod/libtcod.hpp>
#include <string>
#include <memory>
#include <iostream>

namespace Views
{
	enum ViewType
	{
		VIEW_MENU = 0,
		VIEW_GAME,
		VIEW_TYPE_COUNT,
		VIEW_UNKNOWN
	};

	struct ViewContentData
	{
		ViewType type;
		std::string name;
		unsigned int width;
		unsigned int height;
		unsigned int x;
		unsigned int y;
		float foreground_alpha;
		float background_alpha;
		unsigned int alignment;
		std::string background_image;
	};

	class ViewContent : public ITCODParserListener
	{
	public:
		ViewContent(const std::string &view_file)
		{
			data = std::unique_ptr<ViewContentData>(new ViewContentData());

			TCODParser parser;
			auto type = parser.newStructure("view_type");
			type->addProperty("type", TCOD_TYPE_INT, true);
			type->addProperty("width", TCOD_TYPE_INT, true);
			type->addProperty("height", TCOD_TYPE_INT, true);
			type->addProperty("x", TCOD_TYPE_INT, true);
			type->addProperty("y", TCOD_TYPE_INT, true);
			type->addProperty("f_alpha", TCOD_TYPE_FLOAT, true);
			type->addProperty("b_alpha", TCOD_TYPE_FLOAT, true);
			type->addProperty("alignment", TCOD_TYPE_INT, true);
			type->addProperty("b_image", TCOD_TYPE_STRING, false);
			parser.run(view_file.c_str(), this);
		}
		~ViewContent() {}

		ViewType getType() const { return data->type; }
		const std::string &getName() const { return data->name; }
		unsigned int getWidth() const { return data->width; }
		unsigned int getHeight() const { return data->height; }
		unsigned int getX() const { return data->x; }
		unsigned int getY() const { return data->y; }
		float getForegroundAlpha() const { return data->foreground_alpha; }
		float getBackgroundAlpha() const { return data->background_alpha; }
		unsigned int getAlignment() const { return data->alignment; }
		const std::string &getBackgroundImage() const { return data->background_image; }

		bool parserNewStruct(TCODParser *parser,const TCODParserStruct *str,const char *name) override
		{
			data->name = name;
			return true;
		}

		bool parserFlag(TCODParser *parser,const char *name) override
		{
			return true;
		}

		bool parserProperty(TCODParser *parser,const char *name, TCOD_value_type_t vtype, TCOD_value_t value) override
		{
			std::string str_name = name;
			if(str_name == "type")
				data->type = (value.i >= VIEW_TYPE_COUNT ? VIEW_UNKNOWN : (ViewType)value.i);
			else if(str_name == "width")
				data->width = value.i;
			else if(str_name == "height")
				data->height = value.i;
			else if(str_name == "x")
				data->x = value.i;
			else if(str_name == "y")
				data->y = value.i;
			else if(str_name == "f_alpha")
				data->foreground_alpha = value.f;
			else if(str_name == "b_alpha")
				data->background_alpha = value.f;
			else if(str_name == "alignment")
				data->alignment = value.i;
			else if(str_name == "b_image")
				data->background_image = value.s;

			return true;
		}

		bool parserEndStruct(TCODParser *parser,const TCODParserStruct *str, const char *name) override
		{
			return true;
		}

		void error(const char *msg) override
		{
			std::cout << "An error occured while parsing View Content: " << msg << std::endl;
		}

	private:
		std::unique_ptr<ViewContentData> data;
	};
}
